package com.tywj.lib.lifecycle.livedata

import androidx.annotation.MainThread
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer

/**
 * <pre>
 *     author : Taylor Zhang
 *     time   : 2018/5/6
 *     desc   : 观察者只会收到注册之后的数据变化，不会收到旧的数据
 *     version: 1.0.0
 * </pre>
 */
open class SingleLiveEvent<T> : MutableLiveData<T>() {

    internal var valueVersion = 0
        private set
    private val observerMap = HashMap<Observer<in T>, ObserverWrapper<T>>()

    override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        if (owner.lifecycle.currentState == Lifecycle.State.DESTROYED) {
            return
        }

        if (observerMap.containsKey(observer)) {
            return
        }

        val observerWrapper = ObserverWrapper(observer, this)
        observerMap[observer] = observerWrapper
        super.observe(owner, observerWrapper)
    }

    override fun observeForever(observer: Observer<in T>) {
        if (observerMap.containsKey(observer)) {
            return
        }

        val observerWrapper = ObserverWrapper(observer, this)
        observerMap[observer] = observerWrapper
        super.observeForever(observerWrapper)
    }

    override fun removeObserver(observer: Observer<in T>) {
        if (observer is ObserverWrapper) {
            super.removeObserver(observer)
            observerMap.remove(observer.observer)
        } else {
            if (observerMap.containsKey(observer)) {
                observerMap[observer]?.let { super.removeObserver(it) }
                observerMap.remove(observer)
            } else {
                super.removeObserver(observer)
            }
        }
    }

    @MainThread
    override fun setValue(value: T) {
        valueVersion++
        super.setValue(value)
    }

    override fun postValue(value: T) {
        valueVersion++
        super.postValue(value)
    }

    private class ObserverWrapper<T>(
        val observer: Observer<in T>,
        private val liveData: SingleLiveEvent<T>
    ) : Observer<T> {

        private val initVersion = liveData.valueVersion

        override fun onChanged(t: T) {
            if (liveData.valueVersion > initVersion) {
                observer.onChanged(t)
            }
        }
    }
}